<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use TencentCloud\Common\Credential;
use TencentCloud\Common\Profile\ClientProfile;
use TencentCloud\Common\Profile\HttpProfile;
use TencentCloud\Common\Exception\TencentCloudSDKException;
use TencentCloud\Cdn\V20180606\CdnClient;
use TencentCloud\Cdn\V20180606\Models\DescribeCdnDomainLogsRequest;
use Carbon\Carbon;
use \DateTimeZone;
use TencentCloud\Cdn\V20180606\Models\DomainLog;
use App\RequestLog;
use App\Repository;
use InfluxDB2\Client;
use InfluxDB2\Model\WritePrecision;
use InfluxDB2\Point;

class importCDN extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'tencent:importCDN {startAt?} {endAt?}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Import Tencent CDN access logs';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        if(env('INFLUXDB2_URL')) {
            $this->influxDB = new Client([
                "url" => env('INFLUXDB2_URL'),
                "token" => env('INFLUXDB2_TOKEN'),
                "bucket" => env('INFLUXDB2_BUCKET'),
                "org" => env('INFLUXDB2_ORG'),
                "precision" => WritePrecision::NS
            ]);
            $this->influxDBWriteApi = $this->influxDB->createWriteApi();
        }

        $this->cred = new Credential(env('TENCENT_CDN_SECRET_ID'), env('TENCENT_CDN_SECRET_KEY'));

        $httpProfile = new HttpProfile();
        $httpProfile->setEndpoint("cdn.tencentcloudapi.com");

        $clientProfile = new ClientProfile();
        $clientProfile->setHttpProfile($httpProfile);
        $client = new CdnClient($this->cred, "", $clientProfile);

        $req = new DescribeCdnDomainLogsRequest();
        $startAt = $this->argument('startAt');
        $endAt = $this->argument('endAt');

        $date = Carbon::now(new DateTimeZone('GMT+8'));

        if ($startAt) {
            $startAt = new Carbon($startAt, 'GMT+8');
        } else {
            $startAt = $date->subHour();
        }

        if ($endAt) {
            $endAt = new Carbon($endAt, 'GMT+8');
        } else {
            $endAt = $date;
        }


        $params = array(
            'Domain' => "lss233.littleservice.cn",
            'StartTime' => $startAt->format('Y-m-d H:i:s'),
            'EndTime' => $endAt->format('Y-m-d H:i:s')
        );
        $req->fromJsonString(json_encode($params));

        $resp = $client->DescribeCdnDomainLogs($req);

        foreach ($resp->DomainLogs as $log) {
            $this->downloadLog($log);
        }
    }

    private function downloadLog(DomainLog $log)
    {
        $content = file_get_contents($log->LogPath);
        $uncompressed = gzdecode($content);
        foreach (explode("\n", trim($uncompressed)) as $el) {
            try {
                $this->parseLog($el);
            } catch (\Exception $e) {
                // pass
            }
        }
    }
    private function parseLog($str)
    {
        if (preg_match('~(\d{14}) (\d+.\d+.\d+.\d+) lss233\.littleservice\.cn \/repositories\/([^\/\s]+)(\/[^\s]+) (\d+) .+~', $str, $matches)) {
            $created_at = Carbon::createFromFormat('YmdHis', $matches[1], 'GMT+8');
            $repository = Repository::where('name', $matches[3])->firstOrFail();
            if(env('INFLUXDB2_URL')) {
                $point = Point::measurement('crystal')
                            ->addTag('repo', $repository->name)
                            ->addField('path', $matches[4])
                            ->addField('bytes', intval($matches[5]));
                $this->influxDBWriteApi->write($point);
            } else {
                $log = new RequestLog;
                $log->created_at = $created_at;
                $log->ip = $matches[1];
                $log->repository_id = $repository->id;
                $log->path = $matches[4];
                $log->size = intval($matches[5]);
                $log->save();
            }
        }
    }
}
